﻿/*MyPhotoIndex Free Photo Organizer <www.myphotoindex.com>
  Copyright (C) <2006-2010>  <Asaf Yarkoni asaf@yarkoni.net>

  This program is free software: you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation, either version 3 of the License, or
  (at your option) any later version.

  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.

  You should have received a copy of the GNU General Public License
  along with this program.  If not, see <http://www.gnu.org/licenses/>.*/

/*The code in this file (HistogramProcessor.cs) is based on the work of
 * "Asif"
 * which can be found in the following address :http://www.codersource.net/csharp_normalized_histogram.aspx*/

using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing.Imaging;
using System.Drawing;

namespace MyPhotoIndex.Plugins.Histogram
{
    public enum HistogramType { Luminosity, Red, Green, Blue }

    public class HistogramProcessor
    {
        private Bitmap bmpimg;

        public void setImage(Image bmp)
        {
            bmpimg = (Bitmap)bmp.Clone();
        }

        public Bitmap getImage()
        {
            return (Bitmap)bmpimg.Clone();
        }

        public Image CalculateHistogram(HistogramType histogramType)
        {
            BitmapData data = bmpimg.LockBits(new System.Drawing.Rectangle(0, 0, bmpimg.Width, bmpimg.Height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);

            unsafe
            {
                byte* ptr = (byte*)data.Scan0;

                int remain = data.Stride - data.Width * 3;

                int[] histogram = new int[256];

                for (int i = 0; i < data.Height; i++)
                {
                    for (int j = 0; j < data.Width; j++)
                    {
                        int mean = 0;
                        switch (histogramType)
                        {
                            case HistogramType.Luminosity:
                                mean = ptr[0] + ptr[1] + ptr[2];
                                mean /= 3;
                                break;
                            case HistogramType.Red:
                                mean = ptr[2];
                                break;
                            case HistogramType.Green:
                                mean = ptr[1];
                                break;
                            case HistogramType.Blue:
                                mean = ptr[0];
                                break;
                            default:
                                break;
                        }

                        histogram[mean]++;
                        ptr += 3;
                    }

                    ptr += remain;
                }

                bmpimg.UnlockBits(data);
                return drawHistogram(histogram, histogramType);
            }
        }


        public Image drawHistogram(int[] histogram, HistogramType histogramType)
        {
            Bitmap bmp = new Bitmap(histogram.Length + 10, 310);
            BitmapData data = bmp.LockBits(new System.Drawing.Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);

            unsafe
            {
                int remain = data.Stride - data.Width * 3;
                byte* ptr = (byte*)data.Scan0;

                for (int i = 0; i < data.Height; i++)
                {
                    for (int j = 0; j < data.Width; j++)
                    {
                        ptr[0] = ptr[1] = ptr[2] = 255;// 150;
                        ptr += 3;
                    }
                    ptr += remain;

                }

                int max = 0;
                for (int i = 0; i < histogram.Length; i++)
                {
                    max = Math.Max(max, histogram[i]);
                }

                byte pb = 0, pg = 0, pr = 0;
                switch (histogramType)
                {
                    case HistogramType.Red:
                        pr = 255;
                        break;
                    case HistogramType.Green:
                        pg = 255;
                        break;
                    case HistogramType.Blue:
                        pb = 255;
                        break;
                    default:
                        break;
                }

                for (int i = 0; i < histogram.Length; i++)
                {
                    ptr = (byte*)data.Scan0;
                    ptr += data.Stride * (305) + (i + 5) * 3;

                    int length = (int)(1.0 * histogram[i] * 300 / max);

                    for (int j = 0; j < length; j++)
                    {
                        ptr[0] = pb;
                        ptr[1] = pg;
                        ptr[2] = pr;
                        ptr -= data.Stride;
                    }
                }
            }

            bmp.UnlockBits(data);

            return bmp;
        }
    }
}
